<template>
  <div class="validate-input-container pb-3">
    <input
      v-if="tag == 'input'"
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      @blur="validateInput"
      v-bind="$attrs"
      v-model="inputRef.val"
    />
    <textarea
      v-else
      @blur="validateInput"
      v-model="inputRef.val"
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      v-bind="$attrs"
    ></textarea>
    <span v-if="inputRef.error" class="invalid-feedback">{{
      inputRef.message
    }}</span>
  </div>
</template>

<script lang="ts">
import { emitter } from './ValidateForm.vue'
import {
  defineComponent,
  PropType,
  reactive,
  onMounted,
  watch,
  computed
} from 'vue'

const emailReg =
  /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
export type TagType = 'input' | 'textarea'
interface RuleProp {
  type: 'required' | 'email' | 'custom'
  message: string
  validator?: () => boolean
}
export type RulesProp = RuleProp[]
export default defineComponent({
  props: {
    rules: Array as PropType<RulesProp>,
    modelValue: String,
    tag: {
      type: String as PropType<TagType>,
      default: 'input'
    }
  },
  inheritAttrs: false,
  setup(props, context) {
    // const inputRef = reactive({
    //   val: props.modelValue,
    //   error: false,
    //   message: ''
    // })
    const inputRef = reactive({
      val: computed({
        get: () => props.modelValue,
        set: (newVal) => {
          context.emit('update:modelValue', newVal)
        }
      }),
      error: false,
      message: ''
    })
    // watch(
    //   () => props.modelValue,
    //   (newValue) => {
    //     inputRef.val = newValue
    //   }
    // )
    // const updateValue = (e: KeyboardEvent) => {
    //   const targetValue = (e.target as HTMLInputElement).value
    //   inputRef.val = targetValue
    //   context.emit('update:modelValue', targetValue)
    // }
    const validateInput = () => {
      if (props.rules) {
        const allPassed = props.rules.every((item) => {
          inputRef.message = item.message
          let passed = true

          switch (item.type) {
            case 'required':
              passed = inputRef.val.trim() !== ''
              break
            case 'email':
              passed = emailReg.test(inputRef.val)
              break
            case 'custom':
              // 有则返回执行结果，
              passed = item.validator ? item.validator() : true
              break
            default:
              break
          }
          return passed
        })
        inputRef.error = !allPassed
        return allPassed
      }
      return true
    }

    onMounted(() => {
      emitter.emit('form-item-created', validateInput)
    })
    return { validateInput, inputRef }
  }
})
</script>

<style scoped>
.validate-input-container {
  display: inline-block;
  position: relative;
}
.invalid-feedback {
  position: absolute;
}
</style>
